#'###########################################
#'                                          #
#'  ------------------------------------    #
#'  |     COIN     __                  |    #
#'  |            >(' )                 |    #
#'  |              )/                  |    #
#'  |             /  `----/            |    #
#'  |             \  ~=- /             |    #
#'  |   ~^~^~^~^~^~^~^~^~^~^~^~^~^~^   |    #
#'  ------------------------------------    #
#'                                          #
#'###########################################

#' Intervalle maximum entre deux localisations gps (en secondes)
MAX_INTERVAL <- 600

getError <- function (x, ...) {
  UseMethod("getError")
}

StaticError <- setClass("StaticError", representation(data="data.table",
        truePos="data.frame"))

MobileError <- setClass("MobileError", representation(data="MobileData",
        truePos="data.frame"))

getError.StaticData <- function(data) {
  gps <- data.table(data@gps)
  gps$Position <- NULL
  
  argos <- data.table(data@argos)
  #' Les dates argos sont en GMT. On les transforme ensuite en EST pour
  #' les comparer avec le GPS.
 #'  argos[, time := as.POSIXct(time, tz="GMT")]
  #' argos[, time := as.POSIXct(format(time, tz="EST5EDT", usetz=TRUE))]
  
  truePos <- gps[, list(visibility=data@visibility, longitude=mean(longitude, na.rm=TRUE), latitude=mean(latitude, na.rm=TRUE),
                    longsd=sd(longitude, na.rm=TRUE), latsd=sd(latitude, na.rm=TRUE), n=length(longitude)) , by=session]
  
  argos[,  diffLong := argLong - truePos[session, longitude]]
  argos[,  diffLat := argLat - truePos[session, latitude]]
  argos[, distance := sqrt(diffLong^2 + diffLat^2)]
  
  error <- new("StaticError")
  error@data <- argos
  error@truePos <- truePos
  
  return(error)
}


getError.MobileData <- function (data, plot=FALSE, ...) {
	
	#' On recupere les donnees gps moins la colonne position
	gps <- data.table(data@gps)
	gps$position <- NULL
	#' On s'assure que le temps est au bon fuseau horaire
	setkey(gps, time)
	#gps[, time := as.POSIXct(gps[, time], format="%d/%m/%Y %H:%M:%S", tz="EST5EDT")]
	
	argos <- data.table(data@argos)
	
	#' Les dates argos sont en GMT. On les transforme ensuite en EST pour
	#' les comparer avec le GPS.
	setkey(argos, time)
	#argos[, time := as.POSIXct(time, tz="GMT")]
	#argos[, time := as.POSIXct(format(time, tz="EST5EDT", usetz=TRUE))]

	#' Initialisation de la matrice de resultats
	n <- nrow(argos)
	result <- matrix (0, nrow = n, ncol = 3)
	colnames(result) <- c("gpslongitude", "gpslatitude", "gpsinterval")
	#' Iteration sur chacune des localisations argos pour les comparer
	#' aux localisations GPS
	tmpgps <- gps
	for (i in 1:n) {
		#' On recupere les localisations GPS survenant apres la localisation Argos
		localisationDate <- argos[i, time]
		
		indexAfter <- tmpgps[time > localisationDate, which=TRUE][1]
		longitude <- NA
		latitude <- NA
		diffTime <- NA
		
		#' Il existe une localisation GPS avant et apres
		if (!is.na(indexAfter) && indexAfter > 1) {
			#' On recupere les localisations GPS juste avant et juste apres
			interval <- tmpgps[c(indexAfter - 1, indexAfter)]
			#' On garde la difference entre les 2 localisations
			timeDiff <- difftime(interval[2, time], interval[1, time], units="secs")
			latDiff <- interval[2, latitude] - interval[1, latitude]
			longDiff <- interval[2, longitude] - interval[1, longitude]
			
			#' Si l'ecart entre les localisations GPS est inferieur a 10 min
			if (timeDiff < MAX_INTERVAL) {
				#' Calcul de la distance
				distance <- (longDiff^2 + latDiff^2)^0.5
				#' Calcul de l'angle de deplacement
				angle <- atan(latDiff/longDiff)
				
				#' Quand la localisation Argos survient apres la localisation GPS
				diffTime <- difftime(localisationDate, interval[1, time], units="secs")
				
				#' Proportion par rapport a la duree entre les deux localisation GPS
				prop <- as.numeric(diffTime) / as.numeric(timeDiff)
				#' Distance theoriquement parcourue
				distanceDiff <- prop * distance
				
				if (distanceDiff == 0) {
					diffLat <- diffLong <- 0
				} else {
					#' Difference de Latitude
					diffLat <- distanceDiff * sin(angle)
					#' Difference de Longitude
					diffLong <- distanceDiff * cos(angle)
				}
				longitude <- interval[1, longitude] + diffLong
				latitude <- interval[1, latitude] + diffLat
			}
			if (indexAfter > 2) {
				tmpgps <- tmpgps[-(1:(indexAfter - 2))]
			}
		}
		result[i, ] <- c(longitude, latitude, diffTime)
	}
	
	
	argos[, gpsLong := result[, "gpslongitude"]]
	argos[, gpsLat := result[, "gpslatitude"]]
	argos[, gpsInterval := result[, "gpsinterval"]]
	argos[, diffLong := abs(argLong - gpsLong)]
	argos[, diffLat := abs(argLat - gpsLat)]
	argos[, distance := sqrt(diffLong^2 + diffLat^2)]
	
	if (plot) {
		plotMobileResults(data@date, data@gpsId, result, gps, ...)
	}
	
	return (argos)
}

plotMobileResults <- function (date, gps, data, gpsData, resultsPath=".", lc=c("1", "2", "3")){
  data <- data[LC %in% lc]
  collars <- as.factor(data[,id])
  setkey(data, id)
  
  for (collar in levels(collars)) {
    tmp <- data[id==collar]
    locs <- as.character(tmp[, LC])
    png(paste(resultsPath, "/", date, "-", gps, "-", collar, ".png", sep=""), width=900, height=900)
    plot(data[, list(arglong,arglat)], col="red", main=paste("Trajectoire pour le collier", collar))
    textxy(tmp[, arglong], tmp[, arglat], locs, cx=.7)
    points(gpsData[, list(longitude, latitude)], type="l")
    lines(tmp[, list(arglong, arglat)], col="blue")
    lines(tmp[, list(longitude, latitude)], col="green", type="b")
    segments(tmp[, longitude], tmp[, latitude], tmp[, arglong], tmp[, arglat], lty=2)
    dev.off()
  }
}